package wangwenjun.phase2.concurrencypattern.readwritelockseparation.demo01.framework;

/**
 * 设计为包可见的类，其主要目的是不想对外暴露更多的细节
 * 外部只需要调用{@link ReadWriteLockFactory}的工厂方法即可
 *
 * @author ChangLiang
 * @date 2020/6/12
 */
class ReadWriteLockFactoryImpl implements ReadWriteLockFactory {

    /**
     * 定义对象锁
     * 读写锁的实现内部仍旧需要一个锁进行数据同步及线程间的通信
     */
    private final Object MUTEX = new Object();

    /**
     * 当前有多少个线程正在写入 最多只能有1个
     */
    private int writingWriters = 0;

    /**
     * 当前有多少个线程正在等待写入
     */
    private int waitingWriters = 0;

    /**
     * 当前有多少个线程正在read
     */
    private int readingReaders = 0;

    /**
     * read 和write 的偏好设置
     * 控制倾向性 一般来说读写锁非常适用于读多写少的场景
     * 如果preferWriter=false 很多读线程都在读数据 那么写线程很难得到机会来写
     */
    private boolean preferWriter;

    public ReadWriteLockFactoryImpl() {
        this(true);
    }

    public ReadWriteLockFactoryImpl(boolean preferWriter) {
        this.preferWriter = preferWriter;
    }

    @Override
    public Lock getReadLock() {
        return new ReadLock(this);
    }

    @Override
    public Lock getWriteLock() {
        return new WriteLock(this);
    }

    @Override
    public int getWritingWriters() {
        return this.writingWriters;
    }

    @Override
    public int getWaitingWriters() {
        return this.waitingWriters;
    }

    @Override
    public int getReadingReaders() {
        return this.readingReaders;
    }

    void incrementReadingReaders() {
        this.readingReaders++;
    }

    void decrementReadingReaders() {
        this.readingReaders--;
    }

    void incrementWaitingWriters() {
        this.waitingWriters++;
    }

    void decrementWaitingWriters() {
        this.waitingWriters--;
    }

    void incrementWritingWriters() {
        this.writingWriters++;
    }

    void decrementWritingWriters() {
        this.writingWriters--;
    }

    Object getMutex() {
        return this.MUTEX;
    }

    boolean getPreferWriter() {
        return this.preferWriter;
    }

    void changePrefer(boolean preferWriter) {
        this.preferWriter = preferWriter;
    }
}
